package com.wutong.resonance.controller;

import com.wutong.resonance.model.audio.AudioParams;
import com.wutong.resonance.model.audio.enums.AudioType;
import com.wutong.resonance.model.audio.tool.AudioFile;
import com.wutong.resonance.model.audio.tool.AudioPlayer;
import com.wutong.resonance.model.audio.tool.AudioRecorder;
import com.wutong.resonance.model.plugin.drawer.WaveformDrawer;
import com.wutong.resonance.model.plugin.visual.FrequencyAmplitudeVisualizer;
import com.wutong.resonance.model.plugin.visual.SymmetricWaveformVisualizer;
import javafx.fxml.FXML;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.TextField;
import javafx.scene.layout.Pane;
import lombok.extern.slf4j.Slf4j;

import javax.sound.sampled.Mixer;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Objects;

/**
 * 测试控制类
 * @author wutong
 */
@Slf4j
public class TestController {

    private AudioRecorder audioRecorder;
    private AudioPlayer audioPlayer;

    @FXML
    private Pane visualPane;

    @FXML
    private Pane fileVisuralPane;

    @FXML
    private Pane spectrumAnalyzerPane;

    @FXML
    private TextField bufferSizeText;
    @FXML
    private TextField outputAudioFileNameText;

    @FXML
    private ChoiceBox<Mixer.Info> choiceDevice;

    @FXML
    private CheckBox isStreamRecording;

    public void initialize() {
        bufferSizeText.setText("8192");
        choiceDevice.getItems().addAll(AudioRecorder.getAvailableRecordDevices());
        choiceDevice.getSelectionModel().select(0);
        outputAudioFileNameText.setText("output_" + System.currentTimeMillis());
    }

    void loadRecord() {
        audioRecorder = new AudioRecorder.Builder(AudioParams.STEREO_PCM_48K_16B)
                .setDevice(choiceDevice.getSelectionModel().getSelectedItem())
                .setBufferSize(Integer.parseInt(bufferSizeText.getText()))
                .setStreamRecording(isStreamRecording.isSelected())
                .setOutputAudioFileName(outputAudioFileNameText.getText())
                .build();
    }

    @FXML
    void unloadRecord() {
        if (audioRecorder!= null) {
            audioRecorder.close();
        }
        audioRecorder = null;
    }

    @FXML
    void startRecording() {
        unloadRecord();
        loadRecord();
        audioRecorder.register(new SymmetricWaveformVisualizer(audioRecorder.getAudioParams(), Integer.parseInt(bufferSizeText.getText()), visualPane));
        audioRecorder.register(new FrequencyAmplitudeVisualizer(audioRecorder.getAudioParams() ,Integer.parseInt(bufferSizeText.getText()), spectrumAnalyzerPane));
        audioRecorder.startRecording(true);
    }

    void testLength() {
        log.debug("ByteDataLength: {}", audioRecorder.getAudioData().getByteData().length);
        log.debug("FloatDataLength: {}", audioRecorder.getAudioData().getFloatData().length);
        log.debug("FloatMatrixSize: {}x{}", audioRecorder.getAudioData().getFloatMatrix().length, audioRecorder.getAudioData().getFloatMatrix()[0].length);
        log.debug("DoubleDataLength: {}", audioRecorder.getAudioData().getDoubleData().length);
        log.debug("DoubleMatrixSize: {}x{}", audioRecorder.getAudioData().getDoubleMatrix().length, audioRecorder.getAudioData().getDoubleMatrix()[0].length);
        try (FileWriter writer = new FileWriter("E:\\Java\\Resonance Studio\\src\\test\\resources\\data\\FloatMatrix.txt")) {
            writer.write(Arrays.deepToString(audioRecorder.getAudioData().getFloatMatrix()));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @FXML
    void stopRecording() {
        testLength();
        audioRecorder.clear();
        audioRecorder.stopRecording();
    }

    @FXML
    void saveRecording() {
        audioRecorder.save();
    }

    @FXML
    void showFileWave() {
        WaveformDrawer drawer = new WaveformDrawer(fileVisuralPane);
        drawer.draw(new AudioFile(outputAudioFileNameText.getText() + ".wav", AudioType.WAV));
    }

    @FXML
    void clearAllTempWaveFile() {
        Path nowPath = Path.of(System.getProperty("user.dir"));
        for (File file : Objects.requireNonNull(nowPath.toFile().listFiles())) {
            if (file.getName().endsWith("-tmp.wav")) {
                if (file.delete()) {
                    log.info("删除临时文件：{}", file.getName());
                } else {
                    log.error("删除临时文件失败：{}", file.getName());
                }
            }
        }
    }
    @FXML
    void playRecording() {
        if (audioPlayer == null) {
            audioPlayer = new AudioPlayer(new AudioFile(outputAudioFileNameText.getText() + ".wav", AudioType.WAV), AudioParams.STEREO_PCM_48K_16B);
            audioPlayer.register(new SymmetricWaveformVisualizer(AudioParams.STEREO_PCM_48K_16B, Integer.parseInt(bufferSizeText.getText()), visualPane));
            audioPlayer.register(new FrequencyAmplitudeVisualizer(AudioParams.STEREO_PCM_48K_16B ,Integer.parseInt(bufferSizeText.getText()), spectrumAnalyzerPane));
        }
        audioPlayer.play();
    }

    @FXML
    void pauseRecording() {
        audioPlayer.pause();
    }

    @FXML
    void resumeRecording() {
        audioPlayer.resume();
    }

    @FXML
    void stopPlaying() {
        audioPlayer.stop();
        audioPlayer.clear();
        audioPlayer = null;
    }
}
